package com.zjpavt.client.event;

import com.zjpavt.client.Connection;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 事件注册中心 类似于面向切面编程
 * 所有事件单向通知 不存在返回
 * 启动初始化的时候不得依赖于任何其它对象
 * 抽取出所有需要监听的事件 执行任务
 * @author zyc
 */
@Slf4j
public class EventRegisterCenter {
    private static final EventRegisterCenter INSTANCE = new EventRegisterCenter();
    public static EventRegisterCenter getInstance() {
        return INSTANCE;
    }
    private EventRegisterCenter() {
        registerTask(NETWORK_CHANGE,(map)-> {
            Connection.getInstance().refreshLastReceiveDataDate();
            log.info("network changed, new network is:" + map.get(ACTIVE_NETWORK_NAME));
        });

        registerTask(DEVICE_DISCOVER,(map)-> {
            log.info("device discover in mouth:" + map.get(EXT_NUM)+ " device type=" + map.get(DEVICE_NAME));
        });

        registerTask(DEVICE_DISCONNECT,(map)-> {
            log.info("device disconnect in mouth:" + map.get(EXT_NUM)+ " device type=" + map.get(DEVICE_NAME));
        });
    }

    /**
     * 通道回路发生变化通知对象列表
     */
    private List<Runnable> loopChangeTaskList = new ArrayList<>();

    /**
     *
     * @param task 回路增加后执行的事件
     */
    public void addLoopChangeTask(Runnable task) {
        if (task != null) {
            loopChangeTaskList.add(task);
        }
    }
    /**
     * 回路通道数量变化
     */
    public synchronized void onLoopChange() {
        for (Runnable r : loopChangeTaskList) {
            r.run();
        }
    }
    private List<Runnable> doorOpenTaskList = new ArrayList<>();

    /**
     *
     * @param task 开关门状态变化后执行的事件
     */
    public void addDoorOpenTask(Runnable task) {
        if (task != null) {
            doorOpenTaskList.add(task);
        }
    }

    private List<Runnable> doorCloseTaskList = new ArrayList<>();

    public void addDoorCloseTask(Runnable task) {
        if (task != null) {
            doorCloseTaskList.add(task);
        }
    }
    public synchronized void onDoorOpen() {
        for (Runnable r : doorOpenTaskList) {
            r.run();
        }
    }

    public synchronized void onDoorClose() {
        for (Runnable r : doorCloseTaskList) {
            r.run();
        }
    }

    public static final String LIGHT_INIT = "LIGHT_INIT";

    /**
     * 开关门事件  status=open/close
     */
    public static final String DOOR_STATUS_CHANGE = "DOOR_STATUS_CHANGE";
    public static final String DOOR_STATUS_UPDATE = "DOOR_STATUS_UPDATE";
    public static final String STATUS ="STATUS";
    public static final String OPEN ="open";
    public static final String CLOSE ="close";

    /**
     * 按键事件 keyname=(int)0-12
     */
    public static final String KEY_PRESS = "KEY_PRESS";
    public static final String KEY_NAME = "KEY_NAME";
    /**
     * 设备发现事件
     * deviceName= string
     * extNum = int
     */
    public static final String DEVICE_DISCOVER = "DEVICE_DISCOVER";
    public static final String DEVICE_DISCONNECT = "DEVICE_DISCONNECT";
    public static final String DEVICE_NAME = "DEVICE_NAME";
    public static final String EXT_NUM = "EXT_NUM";
    public static final String SERVER = "SERVER";
    /**
     * 温度数据交互
     * DevcieName = String
     */
    public static final String DATA_EXCHANGE = "DATA_EXCHANGE";
//    public static final String DEVICE_NAME = "DEVICE_NAME";


    /**
     * 回路状态改变 推送J指令的时候
     */
    public static final String LOOP_CHANGE = "LOOP_CHANGE";
    public static final String LOOP_STATUS = "LOOP_STATUS";




    /**
     * "NETWORK_CHANGE"
     * "ACTIVE_NETWORK_NAME"
     */
    public static final String NETWORK_CHANGE = "NETWORK_CHANGE";
    public static final String ACTIVE_NETWORK_NAME = "ACTIVE_NETWORK_NAME";

    /**
     * UDP 接收到非本机的数据
     */
    public static final String UDP_RECEIVED = "UDP_RECEIVED";
    public static final String MSG = "MSG";
    public static final String SRC_IP = "SRC_IP";
    public static final String PORT = "PORT";

    public static final String VIDEO = "VIDEO";

    private Map<String, List<RunnableTask>> eventCenter = new ConcurrentHashMap<>();

    /**
     * 注册事件
     * 与下面的事件切面触发一致
     * 当事件触发的时候，会执行任务队列中相关的RunnableTask
     * @param eventName
     * @param runnableTask
     */
    public void registerTask(String eventName,RunnableTask runnableTask) {
//       根据eventName 分段锁住Map
        eventCenter.compute(eventName, (e1, taskList) -> {
            if (taskList != null) {
                taskList.add(runnableTask);
                return taskList;
            } else {
                List<RunnableTask> runnableTasks = new ArrayList<>();
                runnableTasks.add(runnableTask);
                return runnableTasks;
            }
        });
    }

    /***
     * 事件切面
     * @param eventName 触发事件
     * @param map   需要穿的参数 通过map类型强转
     */
    public void triggerRegisterTask(String eventName, Map<String,Object> map) {
        eventCenter.computeIfPresent(eventName, (name, taskList) -> {
            for (RunnableTask task : taskList) {
                task.run(map);
            }
            return taskList;
        });
    }
}
